package cc.rengu.igas.bsps.core.service.trans;

import cc.rengu.igas.bsps.common.constant.BspsAppParamConstant;
import cc.rengu.igas.bsps.common.constant.BspsTreeNodeConstant;
import cc.rengu.igas.bsps.common.dao.BspsMchntAcctInfoMapper;
import cc.rengu.igas.bsps.common.dao.impl.BspsMchntAcctInfoMapperImpl;
import cc.rengu.igas.bsps.common.entity.MchntAcctInfo;
import cc.rengu.igas.bsps.common.entity.RoleAcctInfo;
import cc.rengu.igas.bsps.common.enums.BspsBaseProdEnum;
import cc.rengu.igas.bsps.common.enums.BspsPayTypeEnum;
import cc.rengu.igas.bsps.common.enums.RespCodeEnum;
import cc.rengu.igas.bsps.core.realize.PublicDealService;
import cc.rengu.igas.bsps.core.realize.impl.PublicDealServiceImpl;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.igas.share.common.enums.SettleAcctTypeEnum;
import cc.rengu.igas.share.common.util.GlobalEsbUtil;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.oltp.service.base.RadpService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.entity.MchntOrderInfo;
import cc.rengu.oltp.service.common.entity.PayOrderInfo;
import cc.rengu.oltp.service.common.entity.UserOrderInfo;
import cc.rengu.oltp.service.common.enums.AcctTypeEnum;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.TransStatusEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.TxnInfo;
import cc.rengu.oltp.service.realize.OrderService;
import cc.rengu.oltp.service.realize.TxnInfoService;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.service.realize.impl.TxnInfoServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;

import java.util.Optional;

/**
 * @author: zhangxuran
 * @Date: 2020/5/13 17:55
 * @Description: TODO 异步进行商户D0结算
 */
public class AsynMchntD0SettleService extends RadpService {

    @Override
    protected int bizInit(String s) {
        return 0;
    }

    @Override
    protected int bizProcess(String s, int i) {
        try {
            XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
            UserOrderInfo userOrderInfo = (UserOrderInfo) xmlTreeUtil.getXmlTreeObjectValue(BspsTreeNodeConstant.USER_ORDER_INFO, UserOrderInfo.class);
            MchntOrderInfo mchntOrderInfo = (MchntOrderInfo) xmlTreeUtil.getXmlTreeObjectValue(BspsTreeNodeConstant.MCHNT_ORDER_INFO, MchntOrderInfo.class);
            MchntService mchntService = new MchntServiceImpl();
            MchntInfo mchntInfo = mchntService.getMchntInfo(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo());
            if (null == mchntInfo) {
                rglog.error("获取商户信息失败,mchntNo:<{}>", mchntOrderInfo.getMchntNo());
                throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
            }
            BspsMchntAcctInfoMapper bspsMchntAcctInfoMapper = new BspsMchntAcctInfoMapperImpl();
            MchntAcctInfo mchntAcctInfo;
            if ("11".equals(mchntInfo.getMchntType()) && BspsAppParamConstant.FLAG_N.equals(mchntInfo.getIndependentDataFlag())) {
                //查询连锁商户的结算账户信息
                mchntAcctInfo = bspsMchntAcctInfoMapper.selectBspsMchntAcctInfoByPrimaryKey(mchntOrderInfo.getInstId(),
                        mchntInfo.getChainMchntNo(), BspsBaseProdEnum.ALL.getProdCode(), "00");
            } else {
                mchntAcctInfo = bspsMchntAcctInfoMapper.selectBspsMchntAcctInfoByPrimaryKey(mchntOrderInfo.getInstId(),
                        mchntInfo.getMchntNo(), BspsBaseProdEnum.ALL.getProdCode(), "00");
            }

            if (null == mchntAcctInfo) {
                rglog.error("扫码收款成功，商户为D0结算，但商户结算账户信息查询失败！提现失败请求！");
                throw new BizException(RespCodeEnum.MCHNT_SETTLE_ACCT_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_SETTLE_ACCT_NOT_FOUND.getRespDesc());
            }

            //判断结算账户为本行卡/他行卡
            String payType = getPayType(mchntAcctInfo);
            //暂不支持他行卡D0结算
            if (BspsPayTypeEnum.OTHER_BANK_CARD_PAY.getPayType().equals(payType)) {
                rglog.error("扫码收款成功，商户为D0结算，但商户结算账户信息为他行账户，不支持D0结算");
                return -1;
            }

            OrderService orderService = new OrderServiceImpl();
            PayOrderInfo esbD0payOrderInfo = initEsbPayOrderInfo(payType, mchntOrderInfo, userOrderInfo);
            if (!orderService.registerOrderInfo(null, null, esbD0payOrderInfo)) {
                rglog.error("扫码支付D0结算，新增支付订单失败，提现交易失败！instId:<{}>，sysSeqNum：<{}>",
                        esbD0payOrderInfo.getInstId(), esbD0payOrderInfo.getSysSeqNum());
                throw new BizException(RespCodeEnum.INSERT_ORDER_INFO_ERROR.getRespCode(), RespCodeEnum.INSERT_ORDER_INFO_ERROR.getRespDesc());
            }

            GlobalTransUtil.setCacheValue(TransCacheConstant.USER_ORDER_INFO, userOrderInfo);
            rglog.debug("交易成功,开始调用异步通知.");
            int returnCode = asynnotify.transactionNotice("MchntTransNoticeService", 1, 0, 0);
            if (0 != returnCode) {
                rglog.error("提交交易结果异步通知给商户失败!");
            }

            //TODO 异步进行商户D0结算，由项目组实现ESB模块该交易
//            ChnlMchntInfo chnlMchntInfo = new ChnlMchntInfo();
//            BeanUtil.beanCopy(mchntOrderInfo, chnlMchntInfo);
//            chnlMchntInfo.setSettleOrg(mchntOrderInfo.getAcqInstCode());
//            ChnlPayInfo chnlPayInfo = new ChnlPayInfo();
//            BeanUtil.beanCopy(esbD0payOrderInfo, chnlPayInfo);
//            chnlPayInfo.setRealPayAmt(mchntOrderInfo.getRealSettleAmt());
//            /* step7： 调用ESB进行D0实时结算 */
//            D0RealTimeEntryToBankAcctRequest d0RealTimeEntryToBankAcctRequest = new D0RealTimeEntryToBankAcctRequest();
//            ConvertUtil.convertOutput(d0RealTimeEntryToBankAcctRequest);
//            Header header = d0RealTimeEntryToBankAcctRequest.getHeader();
//            header.setTraceNo(esbD0payOrderInfo.getChannelReconKey());
//            header.setTxnNum(esbD0payOrderInfo.getDstTxnNum());
//            header.setSrcSysId(AppParamConstant.SYS_ID);
//            header.setChanlId(BspsAppParamConstant.BSP_SYS_ID);
//            BeanUtil.beanCopy(esbD0payOrderInfo, chnlPayInfo);
//            // String channelBizType = xmlTreeUtil.getXmlTreeStringValue(BspsTreeNodeConstant.CHANNEL_BIZ_TYPE);
//            //D0实时清算走垫资户,默认记0014
//            chnlPayInfo.setChannelBizType(BspsAppParamConstant.D0_OTHER_BANK_CARD_ESB_CHANNEL_BIZ_TYPE);
//            chnlPayInfo.setPayerAcctInfo(esbD0payOrderInfo.getPayerAcctInfo());
//            chnlPayInfo.setPayeeAcctInfo(mchntAcctInfo.getSettleAcctNo());
//            chnlPayInfo.setPayeeAcctName(mchntAcctInfo.getSettleAcctName());
//            if (mchntBaseInfo.getMchntSettleMode().endsWith("1")) {
//                //收支两线的区别登记,手续费由支出户支出,记清算本金
//                chnlPayInfo.setRealPayAmt(mchntOrderInfo.getRealSettleAmt());
//            } else {
//                chnlPayInfo.setRealPayAmt(mchntOrderInfo.getMchntSettleAmt());
//            }
//            chnlMchntInfo.setMchntNo(mchntOrderInfo.getMchntNo());
//            chnlMchntInfo.setMchntName(mchntOrderInfo.getMchntName());
//            d0RealTimeEntryToBankAcctRequest.setChnlMchntInfo(chnlMchntInfo);
//            d0RealTimeEntryToBankAcctRequest.setChnlPayInfo(chnlPayInfo);
//            /*上送全局流水号*/
//            d0RealTimeEntryToBankAcctRequest.setGlobalTraceNum(GlobalEsbUtil.getGlobalTraceNumber());
//            d0RealTimeEntryToBankAcctRequest.setGlobalPathNum(GlobalEsbUtil.getGlobalPathNumber());
//            DubboService dubboService = new DubboServiceImpl();
//            int iReturnCode = dubboService.asynCallDubboService("coreEsbService", "d0RealTimeEntryToBankAcct", d0RealTimeEntryToBankAcctRequest, "AsynMchntD0AccoutingService");
//            if (iReturnCode != 0) {
//                rglog.error("异步d0入账服务注册失败！");
//            }
            return 0;
        } catch (Exception e) {
            rglog.error("D0清算错误,错误信息<{}>", e.getMessage());
            return -1;
        }
    }

    @Override
    protected int bizTerminate(String s) {
        return 0;
    }

    private String getPayType(MchntAcctInfo mchntAcctInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String payType;
        if (mchntAcctInfo.getSettleAcctType().startsWith("0")) {
            //本行卡
            payType = BspsPayTypeEnum.BANK_CARD_PAY.getPayType();
            // xmlTreeUtil.setXmlTreeStringValue(BspsTreeNodeConstant.CHANNEL_BIZ_TYPE, BspsAppParamConstant.D0_ESB_CHANNEL_BIZ_TYPE);
        } else {
            /* 他行卡 */
            payType = BspsPayTypeEnum.OTHER_BANK_CARD_PAY.getPayType();
            // xmlTreeUtil.setXmlTreeStringValue(BspsTreeNodeConstant.CHANNEL_BIZ_TYPE, BspsAppParamConstant.D0_OTHER_BANK_CARD_ESB_CHANNEL_BIZ_TYPE);
        }
        return payType;
    }

    private PayOrderInfo initEsbPayOrderInfo(String payType,
                                             MchntOrderInfo mchntOrderInfo,
                                             UserOrderInfo userOrderInfo) throws Exception {
        //获取交易配置信息
        TxnInfoService txnInfoService = new TxnInfoServiceImpl();
        TxnInfo txnInfo = txnInfoService.getTxnInfo(userOrderInfo.getInstId(), userOrderInfo.getMsgSrcId(), userOrderInfo.getTransChannelId(), userOrderInfo.getTxnNum(), userOrderInfo.getBizType());

        //D0结算
        Optional<ChannelCallCfg> channelCallCfgOptional = txnInfo.getChannelCallCfgList().stream()
                .filter(item -> ChannelEnum.ESB.getChannelType().equals(item.getCallChannelId()) && "00010000175500".equals(item.getCallChannelTxn())).findFirst();

        if (!channelCallCfgOptional.isPresent()) {
            rglog.error("扫码支付D0提现，通道服务调用配置表无ESB数据！,sysSeqNum:<{}>,",
                    mchntOrderInfo.getSysSeqNum());
            throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
        }
        //获取通道服务调用配置
        ChannelCallCfg channelCallCfg = channelCallCfgOptional.get();

        PayOrderInfo payOrderInfo = new PayOrderInfo();
        ConvertUtil.convertOutput(payOrderInfo);
        payOrderInfo.setSysSeqNum(mchntOrderInfo.getSysSeqNum());
        payOrderInfo.setMchntOrderId(mchntOrderInfo.getSysSeqNum());
        payOrderInfo.setOrderAmt(mchntOrderInfo.getOrderAmt());
        //实际清算本金金额 实际给商户清算的本金，手续费也基于此金额计算
        payOrderInfo.setRealPayAmt(mchntOrderInfo.getRealSettleAmt());
        //交易通道标识
        payOrderInfo.setMsgDstId(channelCallCfg.getCallChannelId());

        String esbSysSeqNum = GlobalEsbUtil.generateEsbSeqeuenceNumber(mchntOrderInfo.getInstId());//ESB流水号
//        String channelSeqNum = mchntOrderInfo.getSysSeqNum() + channelCallCfg.getCallIndex();
        payOrderInfo.setChannelSeqNum(esbSysSeqNum);
        payOrderInfo.setChannelReconKey(esbSysSeqNum);

        payOrderInfo.setDstCallIndex("0");
        payOrderInfo.setDstTxnNum(channelCallCfg.getCallChannelTxn());
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setPayType(payType);
        // String channelBizType = xmlTreeUtil.getXmlTreeStringValue(BspsTreeNodeConstant.CHANNEL_BIZ_TYPE);
        //D0实时清算走垫资户,默认记0014
        payOrderInfo.setChannelBizType(BspsAppParamConstant.D0_OTHER_BANK_CARD_ESB_CHANNEL_BIZ_TYPE);

        BspsMchntAcctInfoMapper bspsMchntAcctInfoMapper = new BspsMchntAcctInfoMapperImpl();
        MchntAcctInfo mchntAcctInfo = bspsMchntAcctInfoMapper.selectBspsMchntAcctInfoByPrimaryKey(mchntOrderInfo.getInstId(),
                mchntOrderInfo.getMchntNo(), BspsBaseProdEnum.ALL.getProdCode(), "00");
        if (mchntAcctInfo == null) {
            rglog.error("扫码支付D0清算，获取商户结算账户信息失败，商户实时入账失败！");
            throw new BizException(RespCodeEnum.RECORD_NOT_FOUND.getRespCode(), RespCodeEnum.RECORD_NOT_FOUND.getRespDesc());
        }
        /* 获取垫资户 */
        SettleAcctTypeEnum settleAcctTypeEnum = SettleAcctTypeEnum.DZ_SUBJECT;
        PublicDealService publicDealService = new PublicDealServiceImpl();
        RoleAcctInfo roleAcctInfo = publicDealService.getInnerAccountByCondition(mchntOrderInfo.getInstId(), settleAcctTypeEnum);
        if (null == roleAcctInfo) {
            rglog.error("机构内部户信息查询失败！拒绝提现请求！userId:<{}>，sysSeqNum：<{}>,mchntNo:<{}>", mchntOrderInfo.getUserId(), mchntOrderInfo.getSysSeqNum(), mchntOrderInfo.getMchntNo());
            throw new BizException(RespCodeEnum.INST_SETTLE_ACCT_NOT_FOUND.getRespCode(), RespCodeEnum.INST_SETTLE_ACCT_NOT_FOUND.getRespDesc());
        }


        //付款方账户类型  - 本行内部户
        payOrderInfo.setPayerAcctType(AcctTypeEnum.BANK_ACCT.getAcctType());
        //付款方账户信息 - 机构内部户
        payOrderInfo.setPayerAcctInfo(roleAcctInfo.getActualAcct());
        //收款方账户类型
        payOrderInfo.setPayeeAcctType(mchntAcctInfo.getSettleAcctType());
        //收款方账户信息
        payOrderInfo.setPayeeAcctInfo(mchntAcctInfo.getSettleAcctNo());
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));

        return payOrderInfo;
    }


}
